package com.morristaedt.mirror.ui;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.iflytek.aiui.AIUIEvent;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.cloud.WakeuperListener;
import com.iflytek.cloud.WakeuperResult;
import com.morristaedt.mirror.MirrorApplication;
import com.morristaedt.mirror.R;
import com.morristaedt.mirror.configuration.ConfigurationSettings;
import com.morristaedt.mirror.modules.ForecastModule;
import com.morristaedt.mirror.modules.voice.AIUIVoice;
import com.morristaedt.mirror.modules.voice.TtsModule;
import com.morristaedt.mirror.modules.voice.VoiceModule;
import com.morristaedt.mirror.utils.JsonParser;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 语音控制展示fragment
 */
public class VoiceFragment extends Fragment {

    private static final String TAG = "VoiceFragment";
    private static final String KEY_TTS = "useTts";
    // 语音唤醒模块
    private VoiceModule mVoiceModule;
    // 智能语音模块AIUI
    private AIUIVoice mAIVoiceModule;
    // 智能语音模块AIUI
    private TtsModule mTtsModule;
    // 闪烁的mic图标
    private ImageView mIvMic;
    // 对话结果展示TextView
    private TextView mSpeechResult;
    // 停止语音命令
    private List<String> STOP_COMMAND = Arrays.asList("再见", "拜拜", "芝麻关门");
    private Handler mHandler = new Handler(Looper.getMainLooper());
    private boolean need2Stop = false;
    private boolean isSendingWrite = false;
    private boolean isSpeaking = false;
    private ConfigurationSettings settings;
    private ForecastModule.ForecastListener forecastListener;

    public static VoiceFragment newInstance(boolean useTts) {
        VoiceFragment fragment = new VoiceFragment();
        Bundle args = new Bundle();
        args.putBoolean(KEY_TTS,useTts);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle args  = getArguments();
        Boolean useTts = true;
        if (args != null){
          useTts =  args.getBoolean(KEY_TTS);
        }
        mVoiceModule = new VoiceModule(getActivity(), mWakeuperListener);
        mAIVoiceModule = new AIUIVoice(getActivity(), aiListener);
        if (useTts){
            mTtsModule = new TtsModule(getActivity());
        }
    }

    /**
     * 同步天气数据
     */
    private void syncWeatherInfo() {
        settings = new ConfigurationSettings(getActivity(), ConfigurationSettings.KEY_WEATHER);
        String raw = settings.getWeatherRaw();
        if (TextUtils.isEmpty(raw) || !settings.isNeed2SyncWeather(new Date())) {
            isSendingWrite = true;
            mAIVoiceModule.wakeUp();

        } else {
            parseWeather(raw);
            mVoiceModule.startWake();
            isSendingWrite = false;
        }
    }

    public void setForecastListener(ForecastModule.ForecastListener listener){
        this.forecastListener = listener;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_voice, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mIvMic = (ImageView) view.findViewById(R.id.iv_listening);
        mSpeechResult = (TextView) view.findViewById(R.id.tv_speeck_result);

        syncWeatherInfo();
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mVoiceModule != null) {
            mVoiceModule.stopWake();
        }
        if (mAIVoiceModule != null) {
            mAIVoiceModule.stopRecordAudio();
        }
        if (mTtsModule != null){
            mTtsModule.stopSpeak();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mVoiceModule == null) {
            mVoiceModule = new VoiceModule(getActivity(), mWakeuperListener);
        }
        if (mAIVoiceModule == null) {
            mAIVoiceModule = new AIUIVoice(getActivity(), aiListener);
        }
        if (!mVoiceModule.isListening()){
            mVoiceModule.startWake();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mVoiceModule != null) {
            mVoiceModule.destroy();
        }
        if (mAIVoiceModule != null) {
            mAIVoiceModule.destroyAgent();
        }
        if (mTtsModule != null){
            mTtsModule.stopSpeak();
            mTtsModule.destroy();
        }
    }

    /**
     * 听写监听器 只有语音转文字功能，弃用
     */
    private RecognizerListener mRecognizerListener = new RecognizerListener() {

        @Override
        public void onBeginOfSpeech() {
            // 此回调表示：sdk内部录音机已经准备好了，用户可以开始语音输入
            Toast.makeText(getActivity(), "开始说话", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onError(SpeechError error) {
            // Tips：
            // 错误码：10118(您没有说话)，可能是录音机权限被禁，需要提示用户打开应用的录音权限。

            Log.i(TAG, "onError: " + error.getPlainDescription(true));

        }

        @Override
        public void onEndOfSpeech() {
            // 此回调表示：检测到了语音的尾端点，已经进入识别过程，不再接受语音输入
            Toast.makeText(getActivity(), "结束说话", Toast.LENGTH_SHORT).show();
            mVoiceModule.releaseSpeech();
            hideListening();
            mVoiceModule.startWake();
        }

        @Override
        public void onResult(final RecognizerResult results, boolean isLast) {
            String text = JsonParser.parseIatResult(results.getResultString());
            mSpeechResult.setVisibility(View.VISIBLE);
            mSpeechResult.append(text);
//            mSpeechResult.setSelection(mSpeechResult.length());
        }


        @Override
        public void onVolumeChanged(int volume, byte[] data) {
            Log.i(TAG, "当前正在说话，音量大小：" + volume);
            Log.d(TAG, "返回音频数据：" + data.length);
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 以下代码用于获取与云端的会话id，当业务出错时将会话id提供给技术支持人员，可用于查询会话日志，定位出错原因
            // 若使用本地能力，会话id为null
            //	if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            //		String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            //		Log.d(TAG, "session id =" + sid);
            //	}
        }
    };

    /**
     * 语音唤醒
     */
    private WakeuperListener mWakeuperListener = new WakeuperListener() {
        @Override
        public void onBeginOfSpeech() {

        }

        @Override
        public void onResult(WakeuperResult result) {
            Log.d(TAG, "onResponse");
            String resultString;
            try {
                String text = result.getResultString();
                JSONObject object;
                object = new JSONObject(text);
                StringBuffer buffer = new StringBuffer();
                buffer.append("【RAW】 " + text);
                buffer.append("\n");
                buffer.append("【操作类型】" + object.optString("sst"));
                buffer.append("\n");
                buffer.append("【唤醒词id】" + object.optString("id"));
                buffer.append("\n");
                buffer.append("【得分】" + object.optString("score"));
                buffer.append("\n");
                buffer.append("【前端点】" + object.optString("bos"));
                buffer.append("\n");
                buffer.append("【尾端点】" + object.optString("eos"));
                resultString = buffer.toString();
                mVoiceModule.releaseWake();
                // 唤醒后将语音交给AIUI模块，开始录音监听
                mAIVoiceModule.wakeUp();
                mAIVoiceModule.startRecordAudio();
//                mVoiceModule.startSpeech();
                showListening();
            } catch (JSONException e) {
                resultString = "结果解析出错";
                e.printStackTrace();
            }
            Log.i(TAG, "唤醒 onResponse: " + resultString);
        }

        @Override
        public void onError(SpeechError speechError) {

        }

        @Override
        public void onEvent(int i, int i1, int i2, Bundle bundle) {

        }

        @Override
        public void onVolumeChanged(int i) {

        }
    };

    /**
     * 智能语音 AIUI 监听回调
     */
    private AIUIVoice.OnVoiceAIListener aiListener = new AIUIVoice.OnVoiceAIListener() {
        @Override
        public void onEvent(AIUIEvent event) {

        }

        @Override
        public void onListening() {
            if (isSendingWrite){
                mAIVoiceModule.writeText("今天的天气");
            }
        }

        @Override
        public void onSleep() {
            mAIVoiceModule.stopRecordAudio();
            mVoiceModule.startWake();
        }

        @Override
        public void onStartVoice() {
            showListening();
        }

        @Override
        public void onStopVoice() {
            hideListening();
            mAIVoiceModule.stopRecordAudio();
            mVoiceModule.startWake();
        }

        /**
         * 发送的语音转文字识别结果
         */
        @Override
        public void onRequestParsed(String sendText) {
            Log.i(TAG, "onRequestParsed: "+sendText);

            if ((sendText.contains("暂停")) && isSpeaking && mTtsModule != null){
                mTtsModule.stopSpeak();
                isSpeaking = false;
                return;
            }
            if (STOP_COMMAND.contains(sendText)) {
                onStopVoice();
                onResponse("","再见");
                need2Stop =true;
            }

        }

        /**
         * 响应结果
         */
        @Override
        public void onResponse(final String raw, final String msg) {
            Log.i(TAG, "onResponse: "+msg+ " isSpeaking:"+isSpeaking);
            if (isSpeaking){
                return;
            }
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (isSendingWrite){
                        isSendingWrite = false;
                        if (raw.contains("weather")) {
                            settings.putWeatherRaw(raw,new Date());
                        }
                        mAIVoiceModule.sleep();
                        mVoiceModule.startWake();
                        parseWeather(raw);
                        return;
                    }
                    if (!need2Stop && !isSpeaking) {
                        mSpeechResult.setVisibility(View.VISIBLE);
                        mSpeechResult.setText(msg);
                        // 读出返回的信息
                        if (mTtsModule != null){
                            mTtsModule.speak(msg,mTtsListener);
                        }
                    }
                }
            });

        }
    };


    /**
     * Tts 语音合成播放监听
     */
    private SynthesizerListener mTtsListener = new SynthesizerListener() {

        @Override
        public void onSpeakBegin() {
            Log.i(TAG,"开始播放");
            isSpeaking =true;
        }

        @Override
        public void onSpeakPaused() {
            Log.i(TAG,"暂停播放");
            isSpeaking =false;

        }

        @Override
        public void onSpeakResumed() {
            Log.i(TAG,"继续播放");
            isSpeaking =true;

        }

        @Override
        public void onBufferProgress(int percent, int beginPos, int endPos,
                                     String info) {

        }

        @Override
        public void onSpeakProgress(int percent, int beginPos, int endPos) {
            // 播放进度

        }

        @Override
        public void onCompleted(SpeechError error) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    isSpeaking =false;
                }
            },2000);
            if (!mIvMic.isShown() && mAIVoiceModule!=null){
                mAIVoiceModule.wakeUp();
                mAIVoiceModule.startRecordAudio();
            }
            if (error == null) {
                Log.i(TAG,"播放完成");
            } else {
                Log.i(TAG,error.getPlainDescription(true));
            }
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
        }
    };

    /**
     * 解析天气Json数据
     */
    private void parseWeather(String raw) {
        Object detail = mAIVoiceModule.getMessageHandler().getDetail(raw);
        if (forecastListener != null) {
            forecastListener.onWeatherToday(detail);
        }
    }

    public void showContent(final String content){
        if (mSpeechResult != null && !TextUtils.isEmpty(content)) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mSpeechResult.setVisibility(View.VISIBLE);
                    mSpeechResult.setText(content);
                }
            });

        }
    }


    /**
     * 正在听 ui效果展示 mic 图标展示
     */
    public void showListening() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (!mIvMic.isShown()) {
                    mIvMic.setVisibility(View.VISIBLE);
                    mIvMic.startAnimation(AnimationUtils.loadAnimation(MirrorApplication.getInstance(), R.anim.pulse));
                }
                need2Stop = false;
            }
        });
    }

    /**
     * 停止
     * 隐藏mic图标
     */
    public void hideListening() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (mIvMic.isShown()) {
                    mIvMic.clearAnimation();
                    mIvMic.setVisibility(View.INVISIBLE);
                }
                mSpeechResult.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mSpeechResult.setVisibility(View.INVISIBLE);
                    }
                },5_000);
            }
        });


    }
}
